package com.mzj.saas.mservice.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.cloudauth20190307.Client;
import com.aliyun.cloudauth20190307.models.DescribeFaceVerifyRequest;
import com.aliyun.cloudauth20190307.models.DescribeFaceVerifyResponse;
import com.aliyun.cloudauth20190307.models.InitFaceVerifyRequest;
import com.aliyun.cloudauth20190307.models.InitFaceVerifyResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.tearpc.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.mzj.saas.commons.HttpUtils;
import com.mzj.saas.commons.KeyWorker;
import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.enums.OSSUploadFileTypeEnum;
import com.mzj.saas.commons.enums.UserLoginTypeEnum;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.auth.AuthConfig;
import com.mzj.saas.mservice.auth.vo.*;
import com.mzj.saas.mservice.lock.Repository.SmartLockAuthRepository;
import com.mzj.saas.mservice.lock.Repository.SmartLockRepository;
import com.mzj.saas.mservice.lock.entity.SmartLock;
import com.mzj.saas.mservice.lock.entity.SmartLockAuth;
import com.mzj.saas.mservice.lock.entity.SmartLockFace;
import com.mzj.saas.mservice.lock.service.LockAppService;
import com.mzj.saas.mservice.oss.service.OSSService;
import com.mzj.saas.mservice.property.entity.CommunityHouseUser;
import com.mzj.saas.mservice.property.entity.MatchUser;
import com.mzj.saas.mservice.property.repository.CommunityHouseUserRepository;
import com.mzj.saas.mservice.property.repository.MatchUserRepository;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.mservice.token.service.TokenService;
import com.mzj.saas.redis.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class InitFaceVerifyService {
    @Autowired
    private AuthConfig authConfig;
    @Value("${auth.callback.url}")
    private String callbackUrl;
    @Value("${contract.tmp.dir}")
    private String contractTmpDir;
    @Autowired
    private RedisService redisService;
    @Autowired
    private AppUserRepository appUserRepository;
    @Autowired
    private OSSService ossService;
    @Autowired
    private CommunityHouseUserRepository communityHouseUserRepository;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private MatchUserRepository matchUserRepository;
    @Autowired
    private SmartLockRepository smartLockRepository;
    @Autowired
    private LockAppService lockAppService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private SmartLockAuthRepository smartLockAuthRepository;
    @Value("${ali.oss.bucket.url}")
    private String ossBucketUrl;
    /*
     *oss地址
     */
    @Value("${ali.oss.bucket}")
    private String bucket;

    @Value("${ali.faceAuthentication.host}")
    private String aliFaceAuthenticationHost;

    @Value("${ali.faceAuthentication.path}")
    private String aliFaceAuthenticationPath;

    @Value("${ali.faceAuthentication.appcode}")
    private String aliFaceAuthenticationAppcode;

    @Value("${ali.idCardOcr.host}")
    private String aliIdCardOcrHost;

    @Value("${ali.idCardOcr.path}")
    private String aliIdCardOcrPath;

    @Value("${ali.idCardOcr.appcode}")
    private String aliIdCardOcrAppcode;

    @Value("${ali.eidAuthentication.appcode}")
    private String aliEidAuthenticationAppcode;

    @Value("${ali.eidAuthentication.url}")
    private String aliEidAuthenticationUrl;

    /**
     * 开始认证前通过本接口获取CertifyId
     *
     * @param vo
     * @return
     * @author shun
     * @date 2022年6月9日
     */
    public ResultBean<Object> getCertifyId(String accessToken, RealPeopleCertificationVO vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }
        AppUser appUser = appUserRepository.findByIdOrEnterpriseUserId(token.getId(), token.getEnterpriseUserId());
        if (appUser == null) {
            return ResultBean.failedResult("当前用户不存在！");
        }
        AppUser users = appUserRepository.findByCardNumber(vo.getCertNo(), UserLoginTypeEnum.CONSUMER.getValue());
        if (users != null) {
            return ResultBean.failedResult("当前身份证已存在，请重新输入！");
        }


        InitFaceVerifyRequest request = new InitFaceVerifyRequest();
        // 请输入场景ID+L。
        request.setSceneId(authConfig.getSceneId());
        // 设置商户请求的唯一标识。
        request.setOuterOrderNo("U" + KeyWorker.nextId());
        // 认证方案。
        request.setProductCode("ID_PRO");
        // 模式。
        request.setModel("LIVENESS");
        request.setCertType("IDENTITY_CARD");
        request.setCertName(vo.getCertName());
        request.setCertNo(vo.getCertNo());
        // MetaInfo环境参数。
        request.setMetaInfo(JSON.toJSONString(vo.getMetaInfo()));
        // request.setCallbackUrl(callbackUrl); 不设置回调地址
        // 推荐，支持服务路由。
        InitFaceVerifyResponse response = initFaceVerifyAutoRoute(request);

        // 不支持服务自动路由。
        // InitFaceVerifyResponse response =
        // initFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request);
        log.info("response:" + JSONObject.toJSONString(response));
        if ("200".equals(response.getCode())) {
            // 更新当前用户的 实人认证ID
            String certifyId = response.getResultObject() == null ? null : response.getResultObject().getCertifyId();
            appUser.setCertifyId(certifyId);
//			appUser.setCardNumber(vo.getCertNo());//身份证
            appUser.setName(vo.getCertName());// 姓名
            appUserRepository.save(appUser);
            // 缓存实人认证 姓名与身份证
            redisService.putCertifyId(certifyId, vo);

            return ResultBean.successfulResult(JSON.toJSONString(response));
        } else {
            return ResultBean.failedResult(response.getMessage());
        }

    }


    /**
     * 认证回调接口 (弃用)
     *
     * @param certifyId
     * @param passed
     * @param subcode
     * @return
     */
    public void callBack(String certifyId, String passed, String subcode) throws Exception {
        log.info("实人认证回调：certifyId={},passed={},subcode={}", certifyId, passed, subcode);
        if ("200".equals(subcode)) {
            if (passed.equals("T")) {
                MaterialInfoVo materialInfoVo = DescribeFaceVerify(certifyId);

                String pictureUrl = materialInfoVo.getPictureUrl();// 照片人脸图片 https地址，有效期15分钟，从查询时开始计时。
                File file = null;
                try {
                    file = download(pictureUrl, certifyId);
                    String picUrl = ossService.putFile(bucket, file, OSSUploadFileTypeEnum.PROVE.toString());
                    String ossFilePath = ossService.getOssFilePath(picUrl);
                    AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                    if (appUser != null) {
                        appUser.setFacePic(ossFilePath);
                        appUser.setCertificationStatus(1);
                        appUserRepository.save(appUser);

                        // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
                        String sql = "select u.* from  saas_community_house_user u where u.status=1 and (u.user_id ='" + appUser.getId() + "'+ or u.mobile=" + appUser.getPhone() + ")";
                        List<CommunityHouseUser> houseUserList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CommunityHouseUser.class));
                        for (CommunityHouseUser communityHouseUser : houseUserList) {
                            communityHouseUser.setHumanFaceImage(ossFilePath);// 人脸头像
                            communityHouseUser.setCardNumber(appUser.getCardNumber());// 身份证号码
                        }
                        communityHouseUserRepository.saveAll(houseUserList);

                    }
                } catch (Exception e) {
                    if (file != null && file.exists()) {
                        file.delete();
                    }
                    AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                    if (appUser != null) {
                        appUser.setCardNumber(null);
                        appUserRepository.save(appUser);
                    }

                } finally {
                    if (file != null && file.exists()) {
                        file.delete();
                    }


                }
            } else {
                AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                if (appUser != null) {
                    appUser.setCardNumber(null);
                    appUserRepository.save(appUser);
                }
                log.info("实人认证回调 认证不通过：certifyId={},passed={},subcode={}", certifyId, passed, subcode);
            }


        } else {
            AppUser appUser = appUserRepository.findByCertifyId(certifyId);
            if (appUser != null) {
                appUser.setCardNumber(null);
                appUserRepository.save(appUser);
            }

            log.info("实人认证回调 认证失败：certifyId={},passed={},subcode={}", certifyId, passed, subcode);
        }


    }


    /**
     * 认证结果接口
     *
     * @param certifyId
     * @return
     */
    public ResultBean<Object> verify(String certifyId) {
        log.info("认证结果接口 " + certifyId);
        // 通过以下代码创建API请求并设置参数。
        DescribeFaceVerifyRequest request = new DescribeFaceVerifyRequest();
        // 请输入场景ID+L。
        request.setSceneId(authConfig.getSceneId());

        request.setCertifyId(certifyId);

        // 推荐，支持服务路由。
        DescribeFaceVerifyResponse response = describeFaceVerifyAutoRoute(request);

        // 不支持服务自动路由。
        // DescribeFaceVerifyResponse response = describeFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request);
        log.info("verify response:" + JSON.toJSONString(response));
        if ("200".equals(response.getCode())) {
            if (response.getResultObject().getPassed().equals("T")) {
                JSONObject object = JSONObject.parseObject(response.getResultObject().getMaterialInfo());
                JSONObject jo = object.getJSONObject("facialPictureFront");
                MaterialInfoVo materialInfoVo = JSONObject.parseObject(String.valueOf(jo), MaterialInfoVo.class);

                String pictureUrl = materialInfoVo.getPictureUrl();

                File file = null;
                try {
                    file = download(pictureUrl, certifyId);
                    String picUrl = ossService.putFile(bucket, file, OSSUploadFileTypeEnum.PROVE.toString());

                    AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                    if (appUser != null) {
                        RealPeopleCertificationVO vo = redisService.getCertifyId(certifyId);
                        String certNo = null;
                        if (vo != null) {
                            certNo = vo.getCertNo();
                            appUser.setCardNumber(certNo);// 身份证
                            appUser.setName(vo.getCertName());// 姓名
                        }
                        appUser.setFacePic(picUrl);
                        appUser.setCertificationStatus(1);
                        appUserRepository.save(appUser);

                        List<CommunityHouseUser> cardNumberAndStatus = communityHouseUserRepository.findByCardNumberAndStatus(certNo, 1);
                        for (CommunityHouseUser numberAndStatus : cardNumberAndStatus) {
                            numberAndStatus.setCardNumber(null);
                        }
                        communityHouseUserRepository.saveAll(cardNumberAndStatus);

                        // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
                        String sql = "select u.* from  saas_community_house_user u where u.status=1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                        log.info("房产成员信息登记表明细SQL:" + sql);
                        List<CommunityHouseUser> houseUserList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CommunityHouseUser.class));
                        for (CommunityHouseUser communityHouseUser : houseUserList) {
                            communityHouseUser.setHumanFaceImage(picUrl);// 人脸头像
                            communityHouseUser.setCardNumber(appUser.getCardNumber());// 身份证号码
                            communityHouseUser.setName(appUser.getName());// 姓名
                            communityHouseUserRepository.save(communityHouseUser);

                        }
                        // 同步更新数据到 承租人库表 m_match_user_stock
                        String stockSql = "select s.* from  m_match_user_stock s where s.delete_status=0 and (s.match_user_id ='" + appUser.getId() + "' or s.phone='" + appUser.getPhone() + "')";
                        List<MatchUser> matchUserList = jdbcTemplate.query(stockSql, new BeanPropertyRowMapper<>(MatchUser.class));
                        for (MatchUser matchUser : matchUserList) {
                            matchUser.setName(appUser.getName());// 姓名
                            matchUserRepository.save(matchUser);
                        }

                        // 同步更新智能锁承租人列表  saas_smart_lock
                        String lockSql = "select u.community_house_id as houseId from  saas_community_house_user u where u.status=1 and u.type = 1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                        List<String> houseId = jdbcTemplate.query(lockSql, new BeanPropertyRowMapper<>(String.class));
                        if (!houseId.isEmpty()) {
                            List<SmartLock> smartLocks = smartLockRepository.findByHouseId(houseId.get(0));
                            for (SmartLock smartLock : smartLocks) {
                                smartLock.setMatchUserName(appUser.getName());// 姓名
                                smartLockRepository.save(smartLock);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("认证结果错误 e={}", e.getMessage());
                    if (file != null && file.exists()) {
                        file.delete();
                    }
                    AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                    if (appUser != null) {
                        appUser.setCardNumber(null);
                        appUserRepository.save(appUser);
                    }

                } finally {
                    if (file != null && file.exists()) {
                        file.delete();
                    }

                }
            } else {
                log.info("实人认证结果接口 认证不通过");
                AppUser appUser = appUserRepository.findByCertifyId(certifyId);
                if (appUser != null) {
                    appUser.setCardNumber(null);
                    appUserRepository.save(appUser);
                }
            }
            HashMap<String, Object> map = new HashMap<>();
            map.put("passed", response.getResultObject().getPassed());
            map.put("msg", SubCodeMsg(response.getResultObject().getSubCode()));
            return ResultBean.successfulResult(map);
        } else {
            AppUser appUser = appUserRepository.findByCertifyId(certifyId);
            if (appUser != null) {
                appUser.setCardNumber(null);
                appUserRepository.save(appUser);
            }
            return ResultBean.failedResult(response.getMessage());
        }
    }

    public String SubCodeMsg(String SubCode) {
        String msg = null;
        if (SubCode.equals("201")) {
            msg = "姓名和身份证不一致";
        } else if (SubCode.equals("202")) {
            msg = "查询不到身份信息";
        } else if (SubCode.equals("203")) {
            msg = "查询不到照片或照片不可用";
        } else if (SubCode.equals("204")) {
            msg = "人脸比对不一致 ";
        } else if (SubCode.equals("205")) {
            msg = "活体检测存在风险 ";
        } else if (SubCode.equals("206")) {
            msg = "业务策略限制 ";
        } else if (SubCode.equals("207")) {
            msg = "人脸与身份证人脸比对不一致 ";
        } else if (SubCode.equals("209")) {
            msg = "权威比对源异常 ";
        } else if (SubCode.equals("210")) {
            msg = "认证通过 ";
        }

        return msg;
    }


    // 通过url下载图片保存到本地
    public File download(String urlString, String certifyId) throws Exception {
        FileOutputStream os = null;
        InputStream is = null;
        File file = null;
        try {
            // 构造URL
            URL url = new URL(urlString);
            // 打开连接
            URLConnection con = url.openConnection();
            // 输入流
            is = con.getInputStream();
            // 1K的数据缓冲
            byte[] bs = new byte[1024];
            // 读取到的数据长度
            int len;
            // 输出的文件流

            String filename = contractTmpDir + certifyId + ".jpeg";  // 下载路径及下载图片名称
            file = new File(filename);

            os = new FileOutputStream(file);
            // 开始读取
            while ((len = is.read(bs)) != -1) {
                os.write(bs, 0, len);
            }
            // 完毕，关闭所有链接
            os.close();
            is.close();
            return file;

        } catch (Exception e) {
            log.error("通过url下载图片保存到本地错误：e={}", e.getMessage());
        } finally {
            // 完毕，关闭所有链接
            os.close();
            is.close();
        }
        return null;
    }


    public MaterialInfoVo DescribeFaceVerify(String certifyId) throws Exception {

        // 通过以下代码创建API请求并设置参数。
        DescribeFaceVerifyRequest request = new DescribeFaceVerifyRequest();
        // 请输入场景ID+L。
        request.setSceneId(authConfig.getSceneId());

        request.setCertifyId(certifyId);

        // 推荐，支持服务路由。
        DescribeFaceVerifyResponse response = describeFaceVerifyAutoRoute(request);

        // 不支持服务自动路由。
        // DescribeFaceVerifyResponse response = describeFaceVerify("cloudauth.cn-shanghai.aliyuncs.com", request);

        if ("200".equals(response.getCode())) {
            if (response.getResultObject() != null) {
                JSONObject object = JSONObject.parseObject(response.getResultObject().getMaterialInfo());
                JSONObject jo = object.getJSONObject("facialPictureFront");
                MaterialInfoVo materialInfoVo = JSONObject.parseObject(String.valueOf(jo), MaterialInfoVo.class);

//				JSONArray ocrPicJsonArray = object.getJSONArray("ocrPictureFront");
//				OcrPictureFrontVo ocrPictureFrontVo = ocrPicJsonArray.getObject(0, OcrPictureFrontVo.class);
//				materialInfoVo.setOcrPictureFront(ocrPictureFrontVo);
                return materialInfoVo;
            } else {
                log.info("调用实人认证认证结果 认证主体附件信息为空：Message={}，Code={}", response.getMessage(), response.getCode());
            }

        } else {
            log.info("调用实人认证认证结果失败：Message={}，Code={}", response.getMessage(), response.getCode());

        }
        return null;
    }


    private InitFaceVerifyResponse initFaceVerifyAutoRoute(InitFaceVerifyRequest request) {
        // 第一个为主区域Endpoint，第二个为备区域Endpoint。
        List<String> endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com",
                "cloudauth.cn-beijing.aliyuncs.com");
        InitFaceVerifyResponse lastResponse = null;
        for (String endpoint : endpoints) {
            try {
                InitFaceVerifyResponse response = initFaceVerify(endpoint, request);
                lastResponse = response;

                // 服务端错误，切换到下个区域调用。
                if (response != null && "500".equals(response.getCode())) {
                    continue;
                }

                return response;
            } catch (Exception e) {
                // 网络异常，切换到下个区域调用。
                if (e.getCause() instanceof TeaException) {
                    TeaException teaException = ((TeaException) e.getCause());
                    if (teaException.getData() != null
                            && "ServiceUnavailable".equals(teaException.getData().get("Code"))) {
                        continue;
                    }
                }

                if (e.getCause() instanceof TeaUnretryableException) {
                    continue;
                }
            }
        }

        return lastResponse;
    }

    private DescribeFaceVerifyResponse describeFaceVerifyAutoRoute(DescribeFaceVerifyRequest request) {
        // 第一个为主区域Endpoint，第二个为备区域Endpoint。
        List<String> endpoints = Arrays.asList("cloudauth.cn-shanghai.aliyuncs.com",
                "cloudauth.cn-beijing.aliyuncs.com");
        DescribeFaceVerifyResponse lastResponse = null;
        for (String endpoint : endpoints) {
            try {
                DescribeFaceVerifyResponse response = describeFaceVerify(endpoint, request);
                lastResponse = response;

                // 服务端错误，切换到下个区域调用。
                if (response != null && "500".equals(response.getCode())) {
                    continue;
                }

                return response;
            } catch (Exception e) {
                // 网络异常，切换到下个区域调用。
                if (e.getCause() instanceof TeaException) {
                    TeaException teaException = ((TeaException) e.getCause());
                    if (teaException.getData() != null && "ServiceUnavailable".equals(
                            teaException.getData().get("Code"))) {
                        continue;
                    }
                }

                if (e.getCause() instanceof TeaUnretryableException) {
                    continue;
                }
            }
        }

        return lastResponse;
    }

    private DescribeFaceVerifyResponse describeFaceVerify(String endpoint, DescribeFaceVerifyRequest request)
            throws Exception {
        Config config = new Config();
        config.setAccessKeyId(authConfig.getAccessKeyId());
        config.setAccessKeySecret(authConfig.getAccessKeySecret());
        config.setEndpoint(endpoint);
        // 设置http代理。
        // config.setHttpProxy("http://xx.xx.xx.xx:xxxx");
        // 设置https代理。
        // config.setHttpsProxy("http://xx.xx.xx.xx:xxxx");
        Client client = new Client(config);

        // 创建RuntimeObject实例并设置运行参数。
        RuntimeOptions runtime = new RuntimeOptions();
        runtime.readTimeout = 10000;
        runtime.connectTimeout = 10000;

        return client.describeFaceVerify(request, runtime);
    }

    private InitFaceVerifyResponse initFaceVerify(String endpoint, InitFaceVerifyRequest request) throws Exception {
        Config config = new Config();
        config.setAccessKeyId(authConfig.getAccessKeyId());
        config.setAccessKeySecret(authConfig.getAccessKeySecret());
        config.setEndpoint(endpoint);
        // 设置http代理。
        // config.setHttpProxy("http://xx.xx.xx.xx:xxxx");
        // 设置https代理。
        // config.setHttpsProxy("https://xx.xx.xx.xx:xxxx");
        Client client = new Client(config);

        // 创建RuntimeObject实例并设置运行参数。
        RuntimeOptions runtime = new RuntimeOptions();
        runtime.readTimeout = 10000;
        runtime.connectTimeout = 10000;

        return client.initFaceVerify(request, runtime);
    }

    /**
     * 身份证实名认证接口
     *
     * @param vo
     * @return
     */
    public ResultBean<Object> authentication(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        String certName = vo.getCertName();
        String certNo = vo.getCertNumber();
        String phone = token.getPhone();
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }
        AppUser appUser = appUserRepository.findByIdOrEnterpriseUserId(token.getId(), token.getEnterpriseUserId());
        if (appUser == null) {
            return ResultBean.failedResult("当前用户不存在！");
        }
        // 阿里云身份证实名认证接口
        String host = "https://jmrnhappy.market.alicloudapi.com";
        String path = "/idcard/validate";
        String method = "POST";
        String appcode = "205afda3a06047d9b83a8f0f546c253c";
        Map<String, String> headers = new HashMap<String, String>();
        // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("idCardNo", certNo);
        bodys.put("name", certName);

        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            // System.out.println(response.toString());
            String s = EntityUtils.toString(response.getEntity());
            ResponseVo vos = JSONUtil.toBean(s, ResponseVo.class);
            ResponseVo.Data data = vos.getData();
            String desc = data.getDesc();
            Integer code = vos.getCode();
            if (code.equals(200) && desc.equals("一致")) {
                AppUser byCardNumber = appUserRepository.findByCardNumber(certNo, UserLoginTypeEnum.CONSUMER.getValue());
                if (byCardNumber != null) {
                    return ResultBean.failedResultOfYesRealName("身份已实名是否更换手机号！");
                }
                if (vo != null) {
                    appUser.setCardNumber(certNo);// 身份证
                    appUser.setName(certName);// 姓名
                }
                appUser.setCertificationStatus(1);
                appUserRepository.save(appUser);
                List<CommunityHouseUser> cardNumberAndStatus = communityHouseUserRepository.findByCardNumberAndStatus(certNo, 1);
                for (CommunityHouseUser numberAndStatus : cardNumberAndStatus) {
                    numberAndStatus.setCardNumber(null);
                }
                communityHouseUserRepository.saveAll(cardNumberAndStatus);
                // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
                String sql = "select u.* from  saas_community_house_user u where u.status=1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                log.info("房产成员信息登记表明细SQL:" + sql);
                List<CommunityHouseUser> houseUserList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CommunityHouseUser.class));
                for (CommunityHouseUser communityHouseUser : houseUserList) {
                    communityHouseUser.setCardNumber(appUser.getCardNumber());// 身份证号码
                    communityHouseUser.setName(appUser.getName());// 姓名
                    communityHouseUser.setMobile(phone);// 手机
                    communityHouseUserRepository.save(communityHouseUser);

                }
                // 同步更新数据到 承租人库表 m_match_user_stock
                String stockSql = "select s.* from  m_match_user_stock s where s.delete_status=0 and (s.match_user_id ='" + appUser.getId() + "' or s.phone='" + appUser.getPhone() + "')";
                List<MatchUser> matchUserList = jdbcTemplate.query(stockSql, new BeanPropertyRowMapper<>(MatchUser.class));
                for (MatchUser matchUser : matchUserList) {
                    matchUser.setName(appUser.getName());// 姓名
                    matchUser.setPhone(phone);// 手机
                    matchUserRepository.save(matchUser);
                }

                // 同步更新智能锁承租人列表  saas_smart_lock
                String lockSql = "select u.community_house_id as houseId from  saas_community_house_user u where u.status=1 and u.type = 1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                List<String> houseId = jdbcTemplate.query(lockSql, new BeanPropertyRowMapper<>(String.class));
                if (!houseId.isEmpty()) {
                    List<SmartLock> smartLocks = smartLockRepository.findByHouseId(houseId.get(0));
                    for (SmartLock smartLock : smartLocks) {
                        smartLock.setMatchUserName(appUser.getName());// 姓名
                        smartLockRepository.save(smartLock);
                    }
                }
                // 同步更新智能锁同住和承租人信息 saas_smart_lock_auth
                List<SmartLockAuth> byMobileList = smartLockAuthRepository.findByMobile(appUser.getPhone());
                if (!byMobileList.isEmpty()) {
                    for (SmartLockAuth smartLockAuth : byMobileList) {
                        smartLockAuth.setUserName(certName);
                        smartLockAuth.setMobile(phone);
                        smartLockAuthRepository.save(smartLockAuth);
                    }
                }
                // 生成新的token
                String accessTokenLet = tokenService.authToken(appUser.getName(), appUser.getPassword(), appUser.getId(),
                        appUser.getPhone(), token.getFlag(), token.getMasterStatus(), token.getEnterpriseId(), token.getLoginType(),
                        appUser.getEnterpriseUserId(), appUser.getCertificationStatus());
                ResultBean<Object> objectResultBean = new ResultBean<>();
                objectResultBean.setResultData(accessTokenLet);
                appUser.setPassword(null);
                objectResultBean.setResultData(appUser);
                return ResultBean.successfulResult(objectResultBean);
            } else {
                return ResultBean.failedResult(vos.getMsg());
            }
        } catch (Exception e) {
            log.error("认证结果错误 e={}", e.getMessage());
            e.printStackTrace();
            return ResultBean.failedResult(e.getMessage());
        }

    }

    /**
     * 人脸身份证实名认证接口
     *
     * @param vo
     * @return
     */
    public ResultBean<Object> faceAuthentication(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }

        IdCard idCard = vo.getIdCard();
        if (idCard == null){
            return ResultBean.failedResultWithMsg("参数有误！");
        }

        String certName = idCard.getName();
        String certNo = idCard.getNum();
        String ossIdFaceUrl = vo.getOssIdFaceUrl();
        String phone = token.getPhone();

        AppUser appUser = appUserRepository.findByIdOrEnterpriseUserId(token.getId(), token.getEnterpriseUserId());
        if (appUser == null) {
            return ResultBean.failedResultWithMsg("当前用户不存在！");
        }
        AppUser byCardNumber = appUserRepository.findByCardNumber(certNo, UserLoginTypeEnum.CONSUMER.getValue());
        if (byCardNumber != null) {
            return ResultBean.failedResultOfYesRealName("身份已实名是否更换手机号！");
        }
        ResultBean<Object> objectResultBean = new ResultBean<>();
        Map<String, Object> resultMap = new HashMap<String, Object>();
        // 阿里云人脸身份证实名认证接口
        String host = aliFaceAuthenticationHost;
        String path = aliFaceAuthenticationPath;
        String method = "POST";
        String appcode = aliFaceAuthenticationAppcode;
        Map<String, String> headers = new HashMap<String, String>();
        // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("id_number", certNo);
        // bodys.put("image", "image");
        // bodys.put("image_url", "http://xj-saas-images.oss-cn-qingdao.aliyuncs.com/ad/202301031672739191065.jpg");
        bodys.put("image_url", ossIdFaceUrl);
        bodys.put("name", certName);


        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            String s = EntityUtils.toString(response.getEntity());
            FaceResponseVo voS = JSONUtil.toBean(s, FaceResponseVo.class);
            // 阿里云返回的结果标识
            Integer resultCode = voS.getResultCode();
            log.info("实名请求结果：{}", JSONUtil.toJsonStr(voS));
            // 阿里云返回的结果信息
            String resultMessage = voS.getResultMessage();
            // 阿里云返回的状态
            String status = voS.getStatus();
            // DOWNLOAD_ERROR 人脸图片下载失败
            if (status.equals("DOWNLOAD_ERROR")) {
                // 1006 人脸图片下载失败
                return ResultBean.failedResultWithMsg("人脸图片下载失败");
            }
            // 系统判断为同一人  1001
            if (resultCode.equals(1001) && resultMessage.equals("系统判断为同一人")) {
                // 去掉图片前缀路径
                String replace = ossIdFaceUrl.replace(ossBucketUrl, "");
                if (vo != null) {
                    appUser.setCardNumber(certNo);// 身份证
                    appUser.setName(certName);// 姓名
                    appUser.setFacePic(replace);

                    appUser.setIdCardContent(JSONUtil.toJsonStr(idCard));
                }
                appUser.setCertificationStatus(1);
                appUserRepository.save(appUser);
                List<CommunityHouseUser> cardNumberAndStatus = communityHouseUserRepository.findByCardNumberAndStatus(certNo, 1);
                if (CollectionUtil.isNotEmpty(cardNumberAndStatus)) {
                    for (CommunityHouseUser numberAndStatus : cardNumberAndStatus) {
                        numberAndStatus.setCardNumber(null);
                        numberAndStatus.setIdCardContent(JSONUtil.toJsonStr(idCard));
                    }
                    communityHouseUserRepository.saveAll(cardNumberAndStatus);
                }
                // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
                String sql = "select u.* from  saas_community_house_user u where u.status=1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                log.info("房产成员信息登记表明细SQL:" + sql);
                List<CommunityHouseUser> houseUserList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(CommunityHouseUser.class));
                if (CollectionUtil.isNotEmpty(houseUserList)) {
                    for (CommunityHouseUser communityHouseUser : houseUserList) {
                        communityHouseUser.setCardNumber(appUser.getCardNumber());// 身份证号码
                        communityHouseUser.setName(appUser.getName());// 姓名
                        communityHouseUser.setMobile(phone);// 手机
                        communityHouseUser.setHumanFaceImage(replace);// 手机
                        communityHouseUser.setUserId(appUser.getId());
                        communityHouseUserRepository.save(communityHouseUser);

                    }
                }
                // 同步更新数据到 承租人库表 m_match_user_stock
                String stockSql = "select s.* from  m_match_user_stock s where s.delete_status=0 and (s.match_user_id ='" + appUser.getId() + "' or s.phone='" + appUser.getPhone() + "')";
                List<MatchUser> matchUserList = jdbcTemplate.query(stockSql, new BeanPropertyRowMapper<>(MatchUser.class));
                if (CollectionUtil.isNotEmpty(matchUserList)) {
                    for (MatchUser matchUser : matchUserList) {
                        matchUser.setName(appUser.getName());// 姓名
                        matchUser.setPhone(phone);// 手机
                        matchUserRepository.save(matchUser);
                    }
                }

                // 同步更新智能锁承租人列表  saas_smart_lock
                String lockSql = "select u.community_house_id from  saas_community_house_user u where u.status=1 and u.type = 1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                List<CommunityHouseUser> communityHouseIdList = jdbcTemplate.query(lockSql, new BeanPropertyRowMapper<>(CommunityHouseUser.class));
                if (!communityHouseIdList.isEmpty()) {
                    for (CommunityHouseUser communityHouseUser : communityHouseIdList) {
                        String communityHouseId = communityHouseUser.getCommunityHouseId();
                        List<SmartLock> smartLocks = smartLockRepository.findByHouseId(communityHouseId);
                        for (SmartLock smartLock : smartLocks) {
                            smartLock.setMatchUserName(appUser.getName());// 姓名
                            smartLockRepository.save(smartLock);
                        }
                    }
                }
                // 同步更新智能锁同住和承租人信息 saas_smart_lock_auth
                // SmartLockAuth smartLockAuth = smartLockAuthRepository.findByMobile(appUser.getPhone());
                List<SmartLockAuth> smartLockAuth = smartLockAuthRepository.findByMobileList(appUser.getPhone());
                if (smartLockAuth != null) {
                    for (SmartLockAuth lockAuth : smartLockAuth) {
                        lockAuth.setUserName(certName);
                        lockAuth.setMobile(phone);
                        smartLockAuthRepository.save(lockAuth);
                    }
                }
                // 删除之前的token
                redisService.deleteLoginToken(accessToken);
                // 生成新的token
                String accessTokenLet = tokenService.authToken(appUser.getName(), appUser.getPassword(), appUser.getId(),
                        appUser.getPhone(), token.getFlag(), token.getMasterStatus(), token.getEnterpriseId(), token.getLoginType(),
                        appUser.getEnterpriseUserId(), appUser.getCertificationStatus());
                objectResultBean.setCode("1000");
                objectResultBean.setMsg("系统判断为同一人");
                appUser.setPassword(null);
                appUser.setSalt(null);
                resultMap.put("accessToken", accessTokenLet);
                resultMap.put("user", appUser);
                objectResultBean.setResultData(resultMap);
                return ResultBean.successfulResult(objectResultBean);
            }
            //  1002：不能确定为同一人
            if (resultCode.equals(1002)) {
                return ResultBean.failedResultWithMsg("不能确定为同一人");
            }
            //   1003：为不同人
            if (resultCode.equals(1003)) {
                return ResultBean.failedResultWithMsg("为不同人");
            }
            //   3001：身份证号与姓名不匹配
            if (resultCode.equals(3001)) {
                // 1005 身份证号与姓名不匹配
                return ResultBean.failedResultWithMsg("身份证号与姓名不匹配");
            }
            //   4001：上传相片质量校验不合格，请重新拍摄上传
            if (resultCode.equals(4001)) {
                // 4001：上传相片质量校验不合格，请重新拍摄上传
                return ResultBean.failedResultWithMsg("上传相片质量校验不合格，请重新拍摄上传");
            }
            // INVALID_ARGUMENT 身份证号参数错误
            // if (status.equals("INVALID_ARGUMENT")) {
            // 	//1004 身份证号参数错误
            // 	objectResultBean.setCode("1004");
            // 	objectResultBean.setMsg("身份证号参数错误");
            // 	return ResultBean.successfulResult(objectResultBean);
            // }

        } catch (Exception e) {
            log.error("认证结果错误 e={}", e.getMessage());
            // e.printStackTrace();
            return ResultBean.failedResultOfException();
        }
        return ResultBean.failedResultWithMsg("查无此人！");
    }

    /**
     * 修改已实名认证信息
     *
     * @param vo
     * @return
     */
    public ResultBean<Object> updateAuthentication(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        String certNo = vo.getCertNumber();
        String certName = vo.getCertName();
        String phone = token.getPhone();// 修改手机号
        AppUser appUser = appUserRepository.findByCardNumber(certNo, UserLoginTypeEnum.CONSUMER.getValue());
        // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
        List<CommunityHouseUser> byCardNumber = communityHouseUserRepository.findByCardNumber(certNo);
        if (byCardNumber != null) {
            for (CommunityHouseUser communityHouseUser : byCardNumber) {
                communityHouseUser.setName(certName);
                communityHouseUser.setMobile(phone);
                communityHouseUserRepository.save(communityHouseUser);
            }
        }
        // 同步更新数据到 承租人库表 m_match_user_stock
        String appUserId = appUser.getId();
        MatchUser matchUser = matchUserRepository.findByMatchUserId(appUserId);
        if (matchUser != null) {
            matchUser.setName(certName);
            matchUser.setPhone(phone);
            matchUserRepository.save(matchUser);
        }
        // 同步更新智能锁承租人列表  saas_smart_lock
        SmartLock smartLock = smartLockRepository.findByMatchUserId(appUserId);
        if (smartLock != null) {
            smartLock.setCommunityName(certName);
            smartLockRepository.save(smartLock);
        }
        // 同步更新智能锁同住和承租人信息 saas_smart_lock_auth
        List<SmartLockAuth> byMobileList = smartLockAuthRepository.findByMobile(appUser.getPhone());
        if (!byMobileList.isEmpty()) {
            for (SmartLockAuth smartLockAuth : byMobileList) {
                smartLockAuth.setUserName(certName);
                smartLockAuth.setMobile(phone);
                smartLockAuthRepository.save(smartLockAuth);
            }
        }
        if (appUser != null) {
            appUser.setName(certName);// 姓名
            appUser.setPhone(phone);// 修改手机号
            // 把新手机号替换到旧账号中，实现数据权限的转移
            appUserRepository.save(appUser);
            // 删除现在新手机号数据
            AppUser appUser1 = new AppUser();
            BeanUtil.copyProperties(appUser,appUser1);
            appUser1.setStatus(2);
            appUser1.setCardNumber(null);
            appUser1.setCertificationStatus(0);
            appUser1.setId(token.getId());
            appUserRepository.save(appUser1);
        }
        // 生成新的token
        String accessTokenLet = tokenService.authToken(appUser.getName(), appUser.getPassword(), appUser.getId(),
                appUser.getPhone(), token.getFlag(), token.getMasterStatus(), token.getEnterpriseId(), token.getLoginType(),
                appUser.getEnterpriseUserId(), appUser.getCertificationStatus());
        return ResultBean.successfulResult(accessTokenLet);
    }

    /**
     * 修改已实名认证信息并进行人脸认证
     *
     * @param vo
     * @return
     */
    public ResultBean<Object> updateFaceAuthentication(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }

        IdCard idCard = vo.getIdCard();
        if (idCard == null){
            return ResultBean.failedResult("参数有误！");
        }

        String certName = idCard.getName();
        String certNo = idCard.getNum();
        String ossIdFaceUrl = vo.getOssIdFaceUrl();
        String phone = token.getPhone();
        String userId = token.getId();

        AppUser appUser = appUserRepository.findByCardNumber(certNo, UserLoginTypeEnum.CONSUMER.getValue());
        ResultBean<Object> objectResultBean = new ResultBean<>();
        // 阿里云人脸身份证实名认证接口
        String host = "https://selfiev2.market.alicloudapi.com";
        String path = "/face/verify_selfie_idnumber";
        String method = "POST";
        String appcode = "ed3c5fd3ff7b4621a9bc18a4960f81aa";
        Map<String, String> headers = new HashMap<String, String>();
        // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("id_number", certNo);
        // bodys.put("image", "image");
        // bodys.put("image_url", "http://xj-saas-images.oss-cn-qingdao.aliyuncs.com/ad/202301031672739191065.jpg");
        bodys.put("image_url", ossIdFaceUrl);
        bodys.put("name", certName);


        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            String s = EntityUtils.toString(response.getEntity());
            FaceResponseVo voS = JSONUtil.toBean(s, FaceResponseVo.class);
            // 阿里云返回的结果标识
            Integer resultCode = voS.getResultCode();
            // 阿里云返回的结果信息
            String resultMessage = voS.getResultMessage();
            // 阿里云返回的状态
            String status = voS.getStatus();
            // DOWNLOAD_ERROR 人脸图片下载失败
            if (status.equals("DOWNLOAD_ERROR")) {
                // 1006 人脸图片下载失败
                objectResultBean.setCode("1006");
                objectResultBean.setMsg("人脸图片下载失败");
                return ResultBean.successfulResult(objectResultBean);
            }
            // 系统判断为同一人  1001
            if (resultCode.equals(1001) && resultMessage.equals("系统判断为同一人")) {
                // 同步更新数据到 房产成员信息登记表明细表 saas_community_house_user
                List<CommunityHouseUser> byCardNumber = communityHouseUserRepository.findByCardNumber(certNo);
                if (byCardNumber != null) {
                    for (CommunityHouseUser communityHouseUser : byCardNumber) {
                        communityHouseUser.setName(certName);
                        communityHouseUser.setMobile(phone);
                        communityHouseUser.setIdCardContent(JSONUtil.toJsonStr(idCard));
                        communityHouseUserRepository.save(communityHouseUser);
                    }
                }
                // 同步更新数据到 承租人库表 m_match_user_stock
                String stockSql = "select s.* from  m_match_user_stock s where s.delete_status=0 and (s.match_user_id ='" + appUser.getId() + "' or s.phone='" + appUser.getPhone() + "')";
                List<MatchUser> matchUserList = jdbcTemplate.query(stockSql, new BeanPropertyRowMapper<>(MatchUser.class));
                for (MatchUser matchUser : matchUserList) {
                    matchUser.setName(appUser.getName());// 姓名
                    matchUser.setPhone(phone);// 手机
                    matchUserRepository.save(matchUser);
                }
                // 同步更新智能锁承租人列表  saas_smart_lock
                String lockSql = "select u.community_house_id as houseId from  saas_community_house_user u where u.status=1 and u.type = 1 and (u.user_id ='" + appUser.getId() + "' or u.mobile='" + appUser.getPhone() + "')";
                List<String> houseId = jdbcTemplate.query(lockSql, new BeanPropertyRowMapper<>(String.class));
                if (!houseId.isEmpty()) {
                    for (String s1 : houseId) {
                        List<SmartLock> smartLocks = smartLockRepository.findByHouseId(s1);
                        for (SmartLock smartLock : smartLocks) {
                            smartLock.setMatchUserName(appUser.getName());// 姓名
                            smartLockRepository.save(smartLock);
                        }
                    }
                }
                // 同步更新智能锁同住和承租人信息 saas_smart_lock_auth
                List<SmartLockAuth> smartLockAuth = smartLockAuthRepository.findByMobileList(appUser.getPhone());
                if (smartLockAuth != null) {
                    for (SmartLockAuth lockAuth : smartLockAuth) {
                        lockAuth.setUserName(certName);
                        lockAuth.setMobile(phone);
                        smartLockAuthRepository.save(lockAuth);
                    }
                }
                if (appUser != null) {
                    appUser.setName(certName);// 姓名
                    appUser.setPhone(phone);// 修改手机号
                    appUser.setIdCardContent(JSONUtil.toJsonStr(idCard));
                    // 把新手机号替换到旧账号中，实现数据权限的转移
                    appUserRepository.save(appUser);
                    // 删除现在新手机号数据
                    AppUser appUser1 = new AppUser();
                    BeanUtil.copyProperties(appUser,appUser1);
                    appUser1.setStatus(2);
                    appUser1.setCardNumber(null);
                    appUser1.setCertificationStatus(0);
                    appUser1.setId(token.getId());
                    appUserRepository.save(appUser1);
                }
                // 生成新的token
                String accessTokenLet = tokenService.authToken(appUser.getName(), appUser.getPassword(), appUser.getId(),
                        appUser.getPhone(), token.getFlag(), token.getMasterStatus(), token.getEnterpriseId(), token.getLoginType(),
                        appUser.getEnterpriseUserId(), appUser.getCertificationStatus());
                objectResultBean.setCode("1000");
                objectResultBean.setMsg("修改成功！");
                objectResultBean.setResultData(accessTokenLet);
                return ResultBean.successfulResult(objectResultBean);
            }
            //  1002：不能确定为同一人
            if (resultCode.equals(1002)) {
                objectResultBean.setCode("1002");
                objectResultBean.setMsg("不能确定为同一人");
                return ResultBean.successfulResult(objectResultBean);
            }
            //   1003：为不同人
            if (resultCode.equals(1003)) {
                objectResultBean.setCode("1003");
                objectResultBean.setMsg("为不同人");
                return ResultBean.successfulResult(objectResultBean);
            }
            //   3001：身份证号与姓名不匹配
            if (resultCode.equals(3001)) {
                // 1005 身份证号与姓名不匹配
                objectResultBean.setCode("1005");
                objectResultBean.setMsg("身份证号与姓名不匹配");
                return ResultBean.successfulResult(objectResultBean);
            }
            //   4001：上传相片质量校验不合格，请重新拍摄上传
            if (resultCode.equals(4001)) {
                // 4001：上传相片质量校验不合格，请重新拍摄上传
                objectResultBean.setCode("4001");
                objectResultBean.setMsg("上传相片质量校验不合格，请重新拍摄上传");
                return ResultBean.successfulResult(objectResultBean);
            }
            // INVALID_ARGUMENT 身份证号参数错误
            // if (status.equals("INVALID_ARGUMENT")) {
            // 	//1007 身份证号参数错误
            // 	objectResultBean.setCode("1007");
            // 	objectResultBean.setMsg("身份证号参数错误");
            // 	return ResultBean.successfulResult(objectResultBean);
            // }
        } catch (Exception e) {
            log.error("认证结果错误 e={}", e.getMessage());
            // e.printStackTrace();
            objectResultBean.setCode("1004");
            objectResultBean.setMsg("身份证号参数错误");
            return ResultBean.failedResult(objectResultBean);
        }
        return ResultBean.failedResult("查无此人！");
    }

    /**
     * 人脸认证并下发智能锁授权
     *
     * @param accessToken
     * @param vo
     * @return
     */
    public ResultBean<Object> faceAuthIssueSmartLockAuth(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }

        CommunityHouseUser communityHouseUser = vo.getCommunityHouseUser();
        String houseId = communityHouseUser.getCommunityHouseId();
        String cardNumber = communityHouseUser.getCardNumber();
        String name = communityHouseUser.getName();
        vo.setCertName(name);
        vo.setCertNumber(cardNumber);

        List<SmartLock> byHouseId = smartLockRepository.findByHouseId(houseId);
        SmartLock smartLock = byHouseId.get(0);
        Long lockId = smartLock.getId();

        try {
            // 人脸三要素校验
            if (!faceAuth(vo)) {
                return ResultBean.failedResultWithMsg("人脸信息有误，请重试！");
            }
        } catch (Exception e) {
            log.error("人脸识别失效" + e.getMessage());
            e.printStackTrace();
            return ResultBean.failedResultWithMsg("人脸识别失败，联系管理员处理！");
        }

        SmartLockFace smartLockFace = new SmartLockFace();
        smartLockFace.setFaceImage(vo.getOssIdFaceUrl());
        smartLockFace.setLockId(lockId);

        SmartLockAuth lockAuth = smartLockAuthRepository.findByHouseIdAndCommunityUserId(houseId, communityHouseUser.getId());
        smartLockFace.setLockAuthId(lockAuth.getId());
        smartLockFace.setAuthType(SmartLockFace.PERMANENT_FLAG_YES);
        ResultBean<Object> resultBean = lockAppService.authFace(accessToken, smartLockFace);
        return resultBean;


    }

    public Boolean faceAuth(AuthenticationVo vo){
        String certName = vo.getCertName();
        String certNo = vo.getCertNumber();
        String ossIdFaceUrl = vo.getOssIdFaceUrl();

        // 阿里云人脸身份证实名认证接口
        // 阿里云人脸身份证实名认证接口
        String host = aliFaceAuthenticationHost;
        String path = aliFaceAuthenticationPath;
        String method = "POST";
        String appcode = aliFaceAuthenticationAppcode;
        Map<String, String> headers = new HashMap<String, String>();
        // 最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        // 根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("id_number", certNo);
        // bodys.put("image", "image");
        // bodys.put("image_url", "http://xj-saas-images.oss-cn-qingdao.aliyuncs.com/ad/202301031672739191065.jpg");
        bodys.put("image_url", ossIdFaceUrl);
        bodys.put("name", certName);
        /**
         * 重要提示如下:
         * HttpUtils请从
         * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
         * 下载
         *
         * 相应的依赖请参照
         * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
         */
        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            String s = EntityUtils.toString(response.getEntity());
            FaceResponseVo voS = JSONUtil.toBean(s, FaceResponseVo.class);
            // 阿里云返回的结果标识
            Integer resultCode = voS.getResultCode();
            // 阿里云返回的结果信息
            String resultMessage = voS.getResultMessage();
            // 系统判断为同一人  1001
            if (resultCode.equals(1001) && "系统判断为同一人".equals(resultMessage)) {
                return true;
            }
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }


    /**
     * 阿里云身份证实名认证接口,身份二要素认证
     * @param vo
     * @return
     */
    public Boolean eidAuthentication(AuthenticationVo vo) {
        String certName = vo.getCertName();
        String cardNumber = vo.getCertNumber();
        String url = aliEidAuthenticationUrl;
        String appcode = aliEidAuthenticationAppcode;
        Map<String, Object> params = new HashMap<>();
        params.put("idcard", cardNumber);
        params.put("name", certName);
        String resultStr = HttpRequest.post(url)
                .header("Authorization", "APPCODE " + appcode)// 头信息，多个头信息多次调用此方法即可
                .form(params)
                .timeout(20000)// 超时，毫秒
                .execute().body();
        cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject(resultStr);
        String resultCode = jsonObject.get("code").toString();
        if (resultCode.equals("0")) {
            String description = jsonObject.getJSONObject("result").getStr("description");
            // 系统判断为同一人
            if (resultCode.equals("0") && description.equals("一致")) {
                return true;
            } else {
                log.error("二要素校验：{}",jsonObject);
                return false;
            }
        }
        return false;
    }


    /**
     * 身份证识别
     *
     * @param accessToken
     * @param vo
     * @return <a>https://market.aliyun.com/products/57124001/cmapi010401.html?spm=5176.2020520132.101.3.6a4d7218ZhL3s9#sku=yuncode4401000018</a>
     */
    public ResultBean<Object> idCardOcr(String accessToken, AuthenticationVo vo) {
        TokenRedisVo token = redisService.findTokenVo(accessToken);
        if (token == null) {
            return ResultBean.failedResultOfToken();
        }

        if (vo == null || vo.getOssIdFaceUrl() == null) {
            return ResultBean.failedResultOfParamWithMsg("图片不能为空");
        }

        String host = aliIdCardOcrHost;
        String path = aliIdCardOcrPath;
        String appcode = aliIdCardOcrAppcode;
        String imgFile = vo.getOssIdFaceUrl();
        String method = "POST";

        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Authorization", "APPCODE " + appcode);
        // 根据API的要求，定义相对应的Content-Type
        headers.put("Content-Type", "application/json; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        // configure配置
        JSONObject configObj = new JSONObject();
        configObj.put("side", "face");
        String config_str = configObj.toString();
        // 拼装请求body的json字符串
        JSONObject requestObj = new JSONObject();
        requestObj.put("image", imgFile);
        if (configObj.size() > 0) {
            requestObj.put("configure", config_str);
        }
        String bodys = requestObj.toString();

        try {
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            int stat = response.getStatusLine().getStatusCode();
            if (stat != 200) {
                log.error("身份证识别失败 response={}", JSONUtil.toJsonStr(response));
                return ResultBean.failedResultWithMsg("识别失败");
            }

            String res = EntityUtils.toString(response.getEntity());
            IdCard resObj = JSON.parseObject(res, IdCard.class);
            if (resObj == null || resObj.is_fake()) {
                return ResultBean.failedResultWithMsg("证件有误");
            }
            return ResultBean.successfulResult(resObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultBean.failedResultWithMsg("识别失败");
    }
}
